package day1105.first;

import day1105.common.MyUtil;
import day1105.common.Student;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static day1105.common.MyUtil.printLine;

/**
 * @author Mr.ma
 * @since 2022/11/5 17:29
 * collect(): 收集操作，包含工具类Collectors，
 * 该工具类中含有大量方法，可以实现之前大多数方法所带来的效果
 * collect()存在重载方法，第一种较为原始，属于底层，第二种是第一种的进一步封装，引入了Collector接口，较为常用
 *      <R> R collect(Supplier<R> supplier,
 *                   BiConsumer<R, ? super T> accumulator,
 *                   BiConsumer<R, R> combiner);
 *          1. Supplier 创建一个存储最新结果的容器。
 *              在并发执行时，这个函数式接口可以被多次调用，每次调用都必须产生一个新的值。
 *          2. BiConsumer<R, ? super T> accumulator 累加器，在元素进入收集器中后执行具体处理操作的地方
 *              实现具体的计算逻辑的，也是整个Collector的核心业务逻辑所在的方法
 *          3. BiConsumer<R, R> combiner 合并器, 在有并行流的时候才会有用，合并每个流的处理结果
 *
 *       <R, A> R collect(Collector<? super T, A, R> collector);
 *          参数为Collector接口（收集器），包含了上述的三个参数，
 *          在使用时，需要传入的参数必须为Collector接口的实现类，
 *          可以是JDK中预先定义Collectors工具类，
 *          也可以是自定义的接口实现类
 *
 * Collectors工具类中的方法大体分为三类：
 *      1、恒等操作：toList(),toSet(),toCollection(),toMap()
 *      2、规约汇总：counting(),summingInt(),averagingInt(),
 *                 maxBy(),minBy(),joining(),reducing()
 *      3、分组操作：groupingBy(),partitioningBy()
 *
 **/
public class CollectTest {
    public static void main(String[] args) {
        List<Student> studentList = MyUtil.createStudentList();
        studentList.stream().forEach(System.out::println);
        printLine("获取含所有学生名的集合");
        List<String> collect = studentList.stream().map(Student::getName).collect(Collectors.toList());
        System.out.println("collect = " + collect);
        printLine("年龄最大的学生");
        Student student = studentList.stream().collect(Collectors.maxBy(Comparator.comparingInt(Student::getAge))).get();
        System.out.println("student = " + student);
        printLine("学生成绩总和");
        Double collect1 = studentList.stream().collect(Collectors.summingDouble(Student::getScore));
        System.out.println("summingDouble = " + collect1);
        Double aDouble = studentList.stream().map(Student::getScore).collect(Collectors.reducing((x1, x2) -> x1 += x2)).get();
        System.out.println("reducing = " + aDouble);
        printLine("学生年龄平均值");
        Double collect2 = studentList.stream().collect(Collectors.averagingInt(Student::getAge));
        System.out.println("collect2 = " + collect2);
        printLine("学生姓名拼接的字符串，间隔符为逗号");
        String collect3 = studentList.stream().map(Student::getName).collect(Collectors.joining(","));
        System.out.println("collect3 = " + collect3);
        printLine("按照班级对学生进行分组");
        Map<String, List<Student>> collect4 = studentList.stream().collect(Collectors.groupingBy(Student::getClazz));
        collect4.forEach((key,value)-> System.out.println(key + " : " + value));
        printLine("统计各班人数");
        Map<String, Long> collect5 = studentList.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.counting()));
        collect5.forEach((key,value)-> System.out.println(key + " : " + value + "人"));
        printLine("按照班级与城市对学生进行分组");
        Map<String, Map<String, List<Student>>> collect6 = studentList.stream().collect(Collectors.groupingBy(Student::getClazz, Collectors.groupingBy(Student::getCity)));
        collect6.forEach((key,value) -> {
            System.out.println("班级 : " + key);
            value.forEach((k,v) -> System.out.println(k + "=" + v));
        });
    }
}
